#ifndef OAPL_H
#define OAPL_H

typedef struct
{
    uint8_t *   i;
    size_t      bits;
    size_t      bytes;
    size_t      current_size;
} api_s;

typedef api_s* api_t;

#define SSE_ALIGN_SIZE  16


#define GOLDEN_RATIO        0x9E3779B9

#define TEA_BLOCK_SIZE      64
#define TEA_KEY_SIZE        128
#define TEA_ROUNDS          32
#define TEA_SUM_MAGIC       ((GOLDEN_RATIO * TEA_ROUNDS) & 0xFFFFFFFF)

#define XTEA_ROUNDS         64
#define XTEA_SUM_MAGIC      ((GOLDEN_RATIO * XTEA_ROUNDS) & 0xFFFFFFFF)

void RC4_init(unsigned char * key, unsigned int key_length);
unsigned char RC4_output(void);

void base64_decode(const char in[4], uint8_t out[3]);
void base64_string_decode(const char * in, uint8_t * out);
void base64_encode(const uint8_t block[3], char out[4], const size_t len);
void base64_string_encode(const uint8_t * block, char * out, size_t len);

void XXTEA_encrypt_block(uint32_t * block, const uint32_t const key[4], uint32_t n);
void XXTEA_decrypt_block(uint32_t * block, const uint32_t const key[4], uint32_t n);

void XTEA_encrypt(uint32_t * block, const uint32_t * const key, const size_t count);
void XTEA_decrypt(uint32_t * block, const uint32_t * const key, const size_t count);

void TEA_encrypt(uint32_t * block, const uint32_t * const key, const size_t count);
void TEA_decrypt(uint32_t * block, const uint32_t * const key, const size_t count);


void api_pow_i(api_t a, const size_t exp);

void api_mul(api_t a, api_t b, api_t c);
void api_mul_s(api_t a, const char * str, api_t c);

void api_xor(api_t a, api_t b, api_t c);
void api_xor_self(api_t a, api_t b);
void api_xor_i(api_t a, const uint32_t val);
void api_xor_set_i(api_t a, const uint8_t val);
void api_xor_s(api_t a, const char * str);

void api_and(api_t a, api_t b, api_t c);
void api_and_self(api_t a, api_t b);
void api_and_i(api_t a, const uint32_t val);
void api_and_set_i(api_t a, const uint8_t val);
void api_and_s(api_t a, const char * str);

void api_or(api_t a, api_t b, api_t c);
void api_or_self(api_t a, api_t b);
void api_or_i(api_t a, const uint32_t val);
void api_or_set_i(api_t a, const uint8_t val);
void api_or_s(api_t a, const char * str);

void api_not(api_t a);

void api_inc(api_t a);

void api_add(api_t a, api_t b, api_t c);
void api_add_self(api_t a, api_t b);
void api_add_s(api_t a, const char * str);

void api_ror(api_t a, size_t shift);
void api_rol(api_t a, size_t shift);

void api_shr(api_t a, size_t shift);
void api_shl(api_t a, size_t shift);

void api_print(api_t);

void string2hexarray(const char * str, uint8_t * hex, size_t hex_size);
uint8_t ascii2hex(const char ascii);

api_t api_init_c(api_t b);
api_t api_init_i(size_t, const uint32_t);
api_t api_init_s(size_t, const char *);

void api_destroy(api_t);

#endif
